package com.fiona.remoting.netty.codec;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.fiona.common.extension.ExtensionLoader;
import com.fiona.core.message.Message;
import com.fiona.core.message.enums.SerializationTypeEnum;
import com.fiona.core.protocol.MessageProtocol;
import com.fiona.remoting.netty.Constants;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;

/**
 * <pre>
 *   0     1     2     3     4     6     7     28    29   30
 *   +-----+-----+-----+-----+-----+-----+-----+-----+----+
 *   |          full length  |    messageKey   |type|codec|
 *   +----------------------------------------------------+
 *   |                                                    |
 *   |                    body                            |
 *   |                                                    |
 *   +----------------------------------------------------+
 * 4B full length（消息长度）    24B messageKey（消息ID）
 * 1B type（消息类型） 1B codec（序列化类型）
 * body（object类型数据）
 * </pre>
 *
 * @author huacongnan
 * @createTime on 2021/3/2
 * @see <a href=
 *      "https://www.cnblogs.com/crazymakercircle/p/10294745.html">LengthFieldBasedFrameDecoder
 *      秒懂</a>
 */

public class MessageEncoder extends MessageToByteEncoder<Message> {
	private static Logger logger = LoggerFactory.getLogger(MessageEncoder.class);

	@Override
	protected void encode(ChannelHandlerContext ctx, Message message, ByteBuf out) {
		try {
			byte[] bodyBytes = null;
			byte messageType = message.getType();
			int fullLength = Constants.HEAD_LENGTH;
			out.writerIndex(out.writerIndex() + 4);
			if (messageType != Constants.HEARTBEAT_REQUEST_TYPE && messageType != Constants.HEARTBEAT_RESPONSE_TYPE) {
				// serialize the object
				String codecName = SerializationTypeEnum.getName(message.getCodec());
				logger.info("codec name: [{}] ", codecName);
				MessageProtocol protocol = ExtensionLoader.getExtensionLoader(MessageProtocol.class)
						.getExtension(codecName);
				bodyBytes = protocol.serialize(message.getData());
				// compress the bytes
				fullLength += bodyBytes.length;
			}
			String id = IdUtil.objectId();
			System.out.println(id);
			System.out.println(id.getBytes().length);
			out.writeBytes(id.getBytes()); //messageKey
			out.writeByte(messageType);
			out.writeByte(message.getCodec());
			if (bodyBytes != null) {
				out.writeBytes(bodyBytes);
			}
			int writeIndex = out.writerIndex();
            out.writerIndex(writeIndex - fullLength - 4);
            out.writeInt(fullLength);
            out.writerIndex(writeIndex);
		} catch (Exception e) {
			logger.error("Encode request error!", e);
		}

	}

}
